<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Painting in Mono Winforms</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="Mono, IronPython, painting, Winforms, tutorial, programming">
<meta name="description" content="Painting in Mono Winforms">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>

<div class="container">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<div class="content">


<a href="/" title="Home">Home</a>&nbsp;
<a href="..">Contents</a>


<h1>Painting in Mono Winforms</h1>


<p>
In this part of the IronPython Mono Winforms tutorial, we will do some painting. 
Painting is used, when we want to change or enhance an existing control. Or if we are 
creating a custom control from scratch. To do the painting, we use the 
painting API provided by the Winforms library. The painting is done within a method, 
that we plug into the <b class="keyword">Paint</b> event. 
</p>

<div class="center">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<p>
The <b>System.Drawing</b> namespace provides access to <b>GDI+</b> basic graphics functionality. 
More advanced functionality is provided in the System.Drawing.Drawing2D, 
System.Drawing.Imaging, and System.Drawing.Text namespaces.
The <b>Graphics</b> class provides methods for drawing on the form.
</p>

<h2>Lines</h2>

<p>
Our first example will draw lines on the <b class="keyword">Form</b> control.
</p>

<div class="codehead">lines.py</div>
<pre class="code">
#!/usr/bin/ipy

import clr

clr.AddReference("System.Windows.Forms")
clr.AddReference("System.Drawing")

from System.Windows.Forms import Application, Form
from System.Drawing import Size, Pen, Color
from System.Drawing.Drawing2D import DashStyle

class IForm(Form):

    def __init__(self):
        self.Text = 'Lines'
        self.Size = Size(280, 270)
        self.Paint += self.OnPaint

        self.CenterToScreen()


    def OnPaint(self, event):

        g = event.Graphics

        pen = Pen(Color.Black, 1)
        pen.DashStyle = DashStyle.Dot
        
        g.DrawLine(pen, 20, 40, 250, 40)

        pen.DashStyle = DashStyle.DashDot
        g.DrawLine(pen, 20, 80, 250, 80)

        pen.DashStyle = DashStyle.Dash
        g.DrawLine(pen, 20, 120, 250, 120)

        pen.DashStyle = DashStyle.DashDotDot
        g.DrawLine(pen, 20, 160, 250, 160)

        pen.DashPattern = (6, 8, 1, 1, 1, 1, 1, 1)
        g.DrawLine(pen, 20, 200, 250, 200)
        
        pen.Dispose()
        g.Dispose()


Application.Run(IForm())
</pre>


<p>
We draw five lines on the form. Each line has different <b class="keyword">DashStyle</b>.  
</p>


<pre class="explanation">
 self.Paint += self.OnPaint
</pre>

<p>
Paint events are delivered to the <b class="keyword">OnPaint()</b> method. 
</p>

<pre class="explanation">
 def OnPaint(self, event):
</pre>

<p>
This is the signature of the <b class="keyword">OnPaint()</b> method. 
</p>


<pre class="explanation">
 g = event.Graphics
</pre>

<p>
In order to paint on the form, we must get the <b class="keyword">Graphics</b> object. 
Painting on a form is actually calling various methods of the <b class="keyword">Graphics</b> object.
</p>

<pre class="explanation">
 pen = Pen(Color.Black, 1)
 pen.DashStyle = DashStyle.Dot
        
 g.DrawLine(pen, 20, 40, 250, 40)
</pre>

<p>
We create a <b class="keyword">Pen</b> object. This object is used 
to draw outlines of shapes. Than we set a dotted 
<b class="keyword">DashStyle</b>. Finally we draw the line with 
the <b class="keyword">DrawLine()</b> method. The first 
parameter is the pen object. The next four values are x and y values 
of starting and ending points of the line. 
</p>

<pre class="explanation">
 pen.DashPattern = (6, 8, 1, 1, 1, 1, 1, 1)
</pre>

<p>
There are several built-in <b class="keyword">DashStyle</b> values. 
We can create our own style
by using the <b class="keyword">DashPattern</b> property. It may look 
difficult at the first sight.
But the pattern is simply a tuple of fill and empty values. 
</p>

<pre class="explanation">
 pen.Dispose()
 g.Dispose()
</pre>

<p>
We release resources. 
</p>

<br>
<img src="/img/gui/ironpython/lines.png" alt="lines">
<div class="figure">Figure: Lines</div>


<h2>Colors</h2>

<p>
A color in Winforms library represents an ARGB (alpha, red, green, blue) 
color. It is a combination of
Alpha, Red, Green, and Blue (RGB) intensity values. There are also 
predefined color names, that we can use
in painting.
</p>

<div class="codehead">colors.py</div>
<pre class="code">
#!/usr/bin/ipy

import clr

clr.AddReference("System.Windows.Forms")
clr.AddReference("System.Drawing")

from System.Windows.Forms import Application, Form, ControlStyles
from System.Drawing import Size, Brushes

class IForm(Form):

    def __init__(self):
        self.Text = 'Colors'       
        self.Size = Size(360, 300)
        self.Paint += self.OnPaint
        
        self.CenterToScreen()


    def OnPaint(self, event):

        g = event.Graphics

        g.FillRectangle(Brushes.Sienna, 10, 15, 90, 60)
        g.FillRectangle(Brushes.Green, 130, 15, 90, 60)
        g.FillRectangle(Brushes.Maroon, 250, 15, 90, 60)
        g.FillRectangle(Brushes.Chocolate, 10, 105, 90, 60)
        g.FillRectangle(Brushes.Gray, 130, 105, 90, 60)
        g.FillRectangle(Brushes.Coral, 250, 105, 90, 60)
        g.FillRectangle(Brushes.Brown, 10, 195, 90, 60)
        g.FillRectangle(Brushes.Teal, 130, 195, 90, 60)
        g.FillRectangle(Brushes.Goldenrod, 250, 195, 90, 60)
        
        g.Dispose()


Application.Run(IForm())
</pre>

<p>
We draw nine rectangles with nine different colors. 
</p>

<pre class="explanation">
 g.FillRectangle(Brushes.Sienna, 10, 15, 90, 60)
</pre>

<p>
The <b class="keyword">FillRectagle()</b> method fills a specified 
rectangle with a brush. A brush can be
a color or a pattern. There are some predefined colors available. We 
can get them from the <b class="keyword">Brushes</b> 
object. The last four values are the x, y values of the topleft point 
and the width and height of the rectangle. 
</p>

<br>
<img src="/img/gui/ironpython/colors.png" alt="Colors">
<div class="figure">Figure: Colors</div>


<h2>Hatches</h2>

<p>
The <b class="keyword">HatchBrush</b> object is used to fill the interiors of the shapes. 
There are several built-in patterns, that we can use.
</p>

<div class="codehead">hatches.py</div>
<pre class="code">
#!/usr/bin/ipy

import clr

clr.AddReference("System.Windows.Forms")
clr.AddReference("System.Drawing")

from System.Windows.Forms import Application, Form
from System.Drawing import Size, Color
from System.Drawing.Drawing2D import HatchBrush, HatchStyle

class IForm(Form):

    def __init__(self):
        self.Text = 'Hatches'
        self.Size = Size(360, 300)
        
        self.Paint += self.OnPaint
        
        self.CenterToScreen()


    def OnPaint(self, event):

        g = event.Graphics

        hb = HatchBrush(HatchStyle.Cross, Color.Black, self.BackColor)
        g.FillRectangle(hb, 10, 15, 90, 60)

        hb = HatchBrush(HatchStyle.Percent05, Color.Black, self.BackColor)
        g.FillRectangle(hb, 130, 15, 90, 60)

        hb = HatchBrush(HatchStyle.SolidDiamond, Color.Black, self.BackColor)
        g.FillRectangle(hb, 250, 15, 90, 60)

        hb = HatchBrush(HatchStyle.DiagonalBrick, Color.Black, self.BackColor)
        g.FillRectangle(hb, 10, 105, 90, 60)

        hb = HatchBrush(HatchStyle.Divot, Color.Black, self.BackColor)
        g.FillRectangle(hb, 130, 105, 90, 60)

        hb = HatchBrush(HatchStyle.Wave, Color.Black, self.BackColor)
        g.FillRectangle(hb, 250, 105, 90, 60)

        hb = HatchBrush(HatchStyle.ZigZag, Color.Black, self.BackColor)
        g.FillRectangle(hb, 10, 195, 90, 60)

        hb = HatchBrush(HatchStyle.Sphere, Color.Black, self.BackColor)
        g.FillRectangle(hb, 130, 195, 90, 60)

        hb = HatchBrush(HatchStyle.Shingle, Color.Black, self.BackColor)
        g.FillRectangle(hb, 250, 195, 90, 60)

        hb.Dispose()
        g.Dispose()


Application.Run(IForm())
</pre>

<p>
This time we fill nine rectangles with nine different patterns, called hatches. 
</p>

<pre class="explanation">
 hb = HatchBrush(HatchStyle.Cross, Color.Black, self.BackColor)
</pre>

<p>
Here we create a <b class="keyword">HatchBrush</b> object. The parameters are the hatch style and the
foreground and the background colors. The background color is set to the color of the form, so that it 
looks like we have drawn onto the form. 
</p>

<pre class="explanation">
 g.FillRectangle(hb, 10, 15, 90, 60)
</pre>

<p>
We fill the rectangle with the specified hatch brush. 
</p>

<br>
<img src="/img/gui/ironpython/hatches.png" alt="Hatches">
<div class="figure">Figure: Hatches</div>

<h2>Basic objects</h2>

<p>
The following example draws some basic shapes on the form control. 
</p>

<div class="codehead">basicshapes.py</div>
<pre class="code">
#!/usr/bin/ipy

import clr

clr.AddReference("System.Windows.Forms")
clr.AddReference("System.Drawing")

from System.Windows.Forms import Application, Form
from System.Drawing import Size, Rectangle, Brushes, Pens, Point
from System.Drawing.Drawing2D import SmoothingMode
from System import Array

class IForm(Form):

    def __init__(self):
        self.Text = 'Basic shapes'
        self.Size = Size(420, 280)
        
        self.Paint += self.OnPaint
        
        self.CenterToScreen()

    def OnPaint(self, event):

        g = event.Graphics
        g.SmoothingMode = SmoothingMode.AntiAlias
        
        g.FillRectangle(Brushes.Gray, 20, 20, 120, 80)
        g.FillRectangle(Brushes.Gray, 180, 20, 80, 80)
        
        g.FillEllipse(Brushes.Gray, 30, 120, 100, 100)
        g.FillEllipse(Brushes.Gray, 160, 130, 100, 70)
        
        p1 = Point(300, 40)
        p2 = Point(340, 15)
        p3 = Point(380, 40)
        p4 = Point(380, 80)
        p5 = Point(340, 105)
        p6 = Point(300, 80)
 
        g.FillPolygon(Brushes.Gray, Array[Point]([p1, p2, p3, p4, p5, p6]))
        g.FillPie(Brushes.Gray, Rectangle(290, 130, 90, 90), 0, 315)

        g.Dispose()

Application.Run(IForm())
</pre>

<p>
The code example draws six shapes on the form. A rectangle, a square, 
a circle, an ellipse, a polygon and a pie. 
</p>

<pre class="explanation">
 g.SmoothingMode = SmoothingMode.AntiAlias
</pre>

<p>
This makes the drawing smoother. 
</p>

<pre class="explanation">
 g.FillRectangle(Brushes.Gray, 20, 20, 120, 80)
</pre>

<p>
This line fills a rectangle with gray color.
The parameters are, the brush color, x, y coordinates of the upper-left corner
of the rectangle and width and height of the rectangle. 
</p>

<pre class="explanation">
 g.FillPolygon(Brushes.Gray, Array[Point]([p1, p2, p3, p4, p5, p6]))
</pre>

<p>
This line draws a polygon, consisting of six single points. 
</p>

<pre class="explanation">
 g.FillPie(Brushes.Gray, Rectangle(290, 130, 90, 90), 0, 315)
</pre>

<p>
This line draws a pie. The last two parameters are the start angle and
sweep angle. In degrees.
</p>

<br>
<img src="/img/gui/ironpython/basicshapes.png" alt="Basic shapes">
<div class="figure">Figure: Basic shapes</div>


<h2>Drawing string</h2>

<p>
To draw string on the Winforms <b class="keyword">Form</b>, we use 
the <b class="keyword">DrawString()</b> method. 
</p>

<div class="codehead">lyrics.py</div>
<pre class="code">
#!/usr/bin/ipy

import clr

clr.AddReference("System.Windows.Forms")
clr.AddReference("System.Drawing")

from System.Windows.Forms import Application, Form
from System.Drawing import Size, Font, SolidBrush
from System.Drawing import PointF, Color

class IForm(Form):

    def __init__(self):
        self.Text = "You know I'm No Good"
        self.Size = Size(380, 450)
        
        self.Paint += self.OnPaint
        
        self.CenterToScreen()


    def OnPaint(self, event):

        g = event.Graphics

        ft = Font("Purisa", 10)
        br = SolidBrush(Color.Black)

        pt = PointF(20.0, 20.0)
        g.DrawString("Meet you downstairs in the bar and heard", ft, br, pt)

        pt = PointF(20.0, 50.0)
        g.DrawString("Your rolled up sleeves and your skull t-shirt", ft, br, pt)

        pt = PointF(20.0, 80.0)
        g.DrawString("You say why did you do it with him today?", ft, br, pt)

        pt = PointF(20.0, 110.0)
        g.DrawString("And sniffed me out like I was tanqueray", ft, br, pt)

        pt = PointF(20.0, 160.0)
        g.DrawString("Cause you're my fella, my guy", ft, br, pt)

        pt = PointF(20.0, 190.0)
        g.DrawString("Hand me your stella and fly", ft, br, pt)

        pt = PointF(20.0, 220.0)
        g.DrawString("By the time I'm out the door", ft, br, pt)

        pt = PointF(20.0, 250.0)
        g.DrawString("You tear me down like roger moore", ft, br, pt)

        pt = PointF(20.0, 300.0)       
        g.DrawString("I cheated myself", ft, br, pt)

        pt = PointF(20.0, 330.0)   
        g.DrawString("Like I knew I would", ft, br, pt)

        pt = PointF(20.0, 360.0)        
        g.DrawString("I told ya, I was trouble", ft, br, pt)

        pt = PointF(20.0, 390.0)       
        g.DrawString("You know that I'm no good", ft, br, pt)
        
        g.Dispose()


Application.Run(IForm())
</pre>

<p>
In our example, we draw lyrics of a song on the Winforms form. 
</p>

<pre class="explanation">
 ft = Font("Purisa", 10)
</pre>

<p>
We use the Purisa font, of 10 pts height.
</p>

<pre class="explanation">
 pt = PointF(20.0, 20.0)   
</pre>

<p>
To draw string on the form, we must use floating point values. 
</p>

<pre class="explanation">
 g.DrawString("Meet you downstairs in the bar and heard", ft, br, pt)
</pre>

<p>
The <b class="keyword">DrawString()</b> method takes the following parameters: text to draw, font, brush and 
the <b class="keyword">PointF</b> object.
</p>

<br>
<img src="/img/gui/ironpython/lyrics.png" alt="Lyrics">
<div class="figure">Figure: Lyrics</div>


<h2>Drawing image</h2>

<p>
In our last example we will draw an image on the <b class="keyword">Form</b> control. 
</p>

<div class="codehead">redrock.py</div>
<pre class="code">
#!/usr/bin/ipy

import sys
import clr

clr.AddReference("System.Windows.Forms")
clr.AddReference("System.Drawing")

from System.Windows.Forms import Application, Form
from System.Drawing import Size, Bitmap, Rectangle


class IForm(Form):

    def __init__(self):
        self.Text = 'Red Rock'
        self.Size = Size(200, 150)

        self.loadImage()
        self.Size = Size(self.castle.Width, self.castle.Height)

        self.Paint += self.OnPaint
        self.CenterToScreen()

    def loadImage(self):
        try:
            self.castle = Bitmap("redrock.png")
        except Exception, e:
            print e.msg
            sys.exit(1)
    

    def OnPaint(self, event):
    
        g = event.Graphics
        r = Rectangle(1, 1, self.castle.Width, self.castle.Height)
        g.DrawImage(self.castle, r)
        
        g.Dispose()
        


Application.Run(IForm())
</pre>

<p>
This code example draws an image of a castle on the form. 
</p>

<pre class="explanation">
 def loadImage(self):
     try:
         self.castle = Bitmap("redrock.png")
     except Exception, e:
         print e.msg
         sys.exit(1)
</pre>

<p>
We load an image of a castle.
</p>

<pre class="explanation">
 r = Rectangle(1, 1, self.castle.Width, self.castle.Height)
</pre>

<p>
We determine the rectangle that we will draw.
</p>

<pre class="explanation">
 g.DrawImage(self.castle, r)
</pre>

<p>
This line actually draws the image. 
</p>

<br>
<img src="/img/gui/ironpython/image.jpg" alt="Image">
<div class="figure">Figure: Image</div>

<hr class="btm">

<p>
In this chapter, we did some painting in Mono Winforms library.  
</p>

<div class="center">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>
<br>



<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡ 
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>


<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified January 30, 2009  <span class="copyright">&copy; 2007 - 2012 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>

